package com.evil.activiti.delegate;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSON;
import com.evil.activiti.util.ActivityUtil;
import com.evil.application.api.RemoteApplicationOrderNodeService;
import com.evil.application.api.RemoteApplicationOrderService;
import com.evil.application.api.RemoteApplicationProcessNodeService;
import com.evil.application.api.RemoteRobotActionService;
import com.evil.common.account.dto.user.UserEnterpriseDTO;
import com.evil.common.activiti.enums.NodeTypeEnum;
import com.evil.common.application.dto.mq.RobotActionMQReqDTO;
import com.evil.common.application.dto.order.node.OrderNodeReqDTO;
import com.evil.common.application.dto.robot.RobotConfigDTO;
import com.evil.common.application.enums.robot.RobotSourceTypeEnum;
import com.evil.common.application.enums.robot.RobotTriggerTypeEnum;
import com.evil.common.core.enums.RCodeEnum;
import com.evil.common.core.exception.BusinessException;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.activiti.bpmn.model.FlowElement;
import org.activiti.bpmn.model.ServiceTask;
import org.activiti.engine.delegate.DelegateExecution;
import org.activiti.engine.delegate.Expression;
import org.activiti.engine.delegate.JavaDelegate;
import org.springframework.stereotype.Component;

/**
 * 流程机器人
 *
 * @author liyang
 * @date 2022-08-08 00:00
 */
@Data
@Slf4j
@Component("RobotDelegate")
@RequiredArgsConstructor
public class RobotDelegate implements JavaDelegate {

    /**
     * 机器人配置
     */
    public final static String ROBOT_CONFIG_EXPRESSION = "robotConfigExpression";
    private Expression robotConfigExpression;

    private DelegateExecution execution;

    private final RemoteApplicationOrderService remoteApplicationOrderService;

    private final RemoteApplicationOrderNodeService remoteApplicationOrderNodeService;

    private final RemoteApplicationProcessNodeService remoteApplicationProcessNodeService;

    private final RemoteRobotActionService remoteRobotActionService;

    @Override
    public void execute(DelegateExecution execution) {
        this.execution = execution;
        String currentActivityId = execution.getCurrentActivityId();
        FlowElement currentFlowElement = execution.getCurrentFlowElement();
        log.info("【机器人】，节点flow:{}", currentActivityId);
        if (currentFlowElement instanceof ServiceTask) {
            Long nodeId = ActivityUtil.restoreFlowNodeId(currentActivityId);
            NodeTypeEnum nodeTypeEnum = ActivityUtil.restoreFlowNodeTypeEnum(currentActivityId);
            if (!nodeTypeEnum.isRobot()) {
                // 防止其他类型节点
                return;
            }
            boolean isAddRobot = NodeTypeEnum.ADD_ROBOT_NODE.getId() == nodeTypeEnum.getId();
            Long orderId = execution.getVariable(ActivityUtil.getProcessOrderIdKey(), Long.class);

            // 机器人配置
            String robotConfigStr = (String) robotConfigExpression.getValue(execution);
            RobotConfigDTO robotConfigDTO = JSON.parseObject(robotConfigStr, RobotConfigDTO.class);
            if (null == robotConfigDTO) {
                throw new BusinessException(RCodeEnum.ACTIVITY_COMPLETE_ERROR);
            }

            String applicationKey = remoteApplicationProcessNodeService.getApplicationKeyByNodeId(nodeId);

            // 节点处理人
            UserEnterpriseDTO robotHandler = remoteApplicationProcessNodeService.getNodeHandlers(new OrderNodeReqDTO(orderId, nodeId)).stream()
                    .findFirst().orElseThrow(() -> new BusinessException(RCodeEnum.ACTIVITY_ASSIGNEE_NOT_EXIST).formatMessage(currentFlowElement.getName()));

            RobotActionMQReqDTO robotActionReqDTO = BeanUtil.copyProperties(robotConfigDTO, RobotActionMQReqDTO.class);
            robotActionReqDTO.setEnterpriseId(robotHandler.getEnterpriseId());
            robotActionReqDTO.setApplicationKey(applicationKey);
            robotActionReqDTO.setOrderId(orderId);
            robotActionReqDTO.setTriggerType(isAddRobot ? RobotTriggerTypeEnum.ADD.getId() : RobotTriggerTypeEnum.MODIFY.getId());
            robotActionReqDTO.setHandler(robotHandler);
            robotActionReqDTO.setTriggerId(nodeId);
            robotActionReqDTO.setTriggerName(currentFlowElement.getName());
            robotActionReqDTO.setRobotSourceTypeEnum(RobotSourceTypeEnum.PROCESS_NODE_ROBOT);
            robotActionReqDTO.setSaveNow(true);
            remoteRobotActionService.robotActionBeforeLog(robotActionReqDTO);
        }
    }
}
